package edu.nctu.csie.jichang.database.util;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Reader;
import java.sql.Clob;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.UUID;

import org.apache.commons.io.IOUtils;
import org.postgresql.util.Base64;
import org.springframework.util.DigestUtils;

public class StringUtil {

	public static final String CHANGE_LINE = System.getProperty("line.separator");
	public static final String EMPTY = "".intern();
	public static final String TAB = "\t";

	/**
	 * 是空的時候返回 true
	 * 
	 * @param pValue
	 * @return
	 */
	public static boolean isEmptyOrSpace(final Object pValue){
		if(pValue == null){
			return true;
		}
		return false;
	}
	
	/**
	 * 是空的時候返回 true
	 * @param pValue
	 * @return
	 */
	public static boolean isEmptyOrSpace(final String pValue){
		if(pValue == null || pValue.length()<=0){
			return true;
		}
		return false;
	}

	/**
	 * 是空的時候返回 true
	 * 
	 * @param pValue
	 * @return
	 */
	public static boolean isEmptyOrSpace(final Object[] pValue) {
		if (pValue == null || pValue.length <= 0) {
			return true;
		}
		return false;
	}

	/**
	 * 是空的時候返回 true
	 * 
	 * @param pValue
	 * @return
	 */
	public static boolean isEmptyOrSpace(final Collection<?> pValue) {
		if (pValue == null || pValue.size() <= 0) {
			return true;
		}
		return false;
	}

	public static boolean isEmptyOrZero(final int pValue) {
		return pValue == 0;
	}
	
	/**
	 * 非空的時候返回 true
	 * 
	 * @param pValue
	 * @return
	 */
	public static boolean isNotEmptyOrSpace(final String pValue) {
		return !isEmptyOrSpace(pValue);
	}

	/**
	 * 非空的時候返回 true
	 * 
	 * @param pValue
	 * @return
	 */
	public static boolean isNotEmptyOrSpace(final Object[] pValue) {
		return !isEmptyOrSpace(pValue);
	}

	/**
	 * 非空的時候返回 true
	 * 
	 * @param pValue
	 * @return
	 */
	public static boolean isNotEmptyOrSpace(final Collection<?> pValue) {
		return !isEmptyOrSpace(pValue);
	}
	public static boolean isNotEmptyOrZero(final int pValue) {
		return !isEmptyOrZero(pValue);
	}
	public static boolean isEmptyOrZero(final Object pValue) {
		return pValue == null;
	}
	public static boolean isNotEmptyOrSpace(final Object pValue) {
		return !isEmptyOrSpace(pValue);
	}
	
	/**
	 * 清除前後空白
	 * @param pValue
	 * @return
	 */
	public static String trimNull(final Object pValue) {
		if (pValue == null) {
			return "";
		}
		if (pValue instanceof String) {
			String tString = (String) pValue;
			return tString.trim();
		}
		return String.valueOf(pValue).trim();
	}

	/**
	 * 將字串最後面的 ';' ',' 移除
	 * 
	 * @param pInput
	 * @return
	 */
	public static String trimLastChar(final String pInput) {
		String tOut = "";
		if (isNotEmptyOrSpace(pInput)) {
			String tTemp = new String(pInput).trim();
			char tChar = tTemp.charAt(tTemp.length() - 1);
			if (tChar == ',' || tChar == ';' || tChar == '.' || tChar == '\n') {
				tOut = tTemp.substring(0, tTemp.length() - 1);
			}else{
				return pInput;
			}
		}
		return tOut;
	}
	
	/**
	 * 唯一識別碼,亂數
	 * @return
	 */
	public static String getUUID() {
		return UUID.randomUUID().toString();
	}

	public static String getRandomPassword(int pLength){
		StringBuffer tOut = new StringBuffer();
		int[] tIntAry = new int[pLength];
		int tType;
		for(int i = 0; i < pLength; i++){
			tType = (int)((Math.random()*7)%3);
			if(tType ==1){
				tIntAry[i]=(int)((Math.random()*10) + 48);
			}else if(tType ==2){
				tIntAry[i] = (char)((Math.random()*26) + 65);
			}else{
				tIntAry[i] = (char)((Math.random()*26) + 97);
			}
		}
		for(int j = 0; j < pLength; j++){
			tOut.append((char)tIntAry[j]);
		}
		return tOut.toString();
	}

	
	/**
	 * 編碼
	 * @param pText
	 * @return 
	 * 999999
	 */
	public static String encodeBASE64(Clob pClob) { 
		if (pClob == null) return null;
		try {
			return Base64.encodeBytes(IOUtils.toByteArray(pClob.getAsciiStream()));
		} catch (Exception e) {
			throw new DBException(e);
		}
	}
	
	/**
	 * 解碼
	 * @param pText
	 * @return
	 */
	public static InputStream decodeBASE64(String pText) {
		try {
			return isEmptyOrSpace(pText)?null : new ByteArrayInputStream(Base64.decode(pText));
		} catch (Exception e) { 
			throw new DBException(e);
		} 
	}

	/**
	 * 處理字串截斷
	 * 
	 * @param pDesc
	 * @param pMaxLength
	 * @return
	 */
	public static String getMaxLength(final String pDesc, int pMaxLength) {
		if (pDesc == null) {
			return EMPTY;
		}
		if (pDesc.length() <= pMaxLength) {
			return pDesc;
		} else {
			return pDesc.substring(0, pMaxLength);
		}

	}

	/**
	 * String to Double
	 * @param pValue
	 * @return
	 */
	public static double getDouble(String pValue) {
		try {
			if (pValue != null) {
				return Double.parseDouble(pValue);
			}
		} catch (Exception e) {
		}
		return 0;
	}

	/**
	 * String to Float
	 * @param pValue
	 * @return
	 */
	public static float getFloat(String pValue) {
		try {
			if (pValue != null) {
				return Float.parseFloat(pValue);
			}
		} catch (Exception e) {
		}
		return 0;
	}

	/**
	 * String to Integer
	 * @param pValue
	 * @return
	 */
	public static int getInteger(String pValue) {
		try {
			if (pValue != null) {
				return Integer.parseInt(pValue.trim());
			}
		} catch (Exception e) {
		}
		return 0;
	}
	/**
	 * String[] to Integer[]
	 * @param pValueAry
	 * @return
	 */
	public static Integer[] getInteger(String[] pValueAry) {
		Integer[] tOut = new Integer[pValueAry.length];
		for (int i = 0; i < pValueAry.length; i++) {
			tOut[i] = getInteger(pValueAry[i]);
		}
		return tOut;
	}

	/**
	 * String to Long
	 * @param pValue
	 * @return
	 */
	public static long getLong(String pValue) {
		try {
			if (pValue != null) {
				return Long.parseLong(pValue);
			}
		} catch (Exception e) {
		}
		return 0;
	}

	/**
	 * String to Boolean
	 * @param pValue
	 * @return
	 */
	public static boolean getBoolean(String pValue) {
		if (pValue == null) {
			return false;
		}
		if ("1".equals(pValue) || "true".equalsIgnoreCase(pValue) || "on".equals(pValue)) {
			return true;
		}
		return false;
	}

	/**
	 * 將 list 轉成 字串
	 * @param pList
	 * @return
	 */
	public static String listToString(List<?> pList){
		String tOut = EMPTY;
		if(isNotEmptyOrSpace(pList)){
			for (Object object : pList) {
				tOut += object +",";
			}
		}
		return trimLastChar(tOut);
	}

	/**
	 * 將物件轉成字串
	 * @param pObject
	 * @return
	 */
	public static String getString(Object pObject) {
		if(pObject == null){
			return "";
		}else if (pObject instanceof String) {
			return (String)pObject;
		}else if (pObject instanceof Object[]) {
			if(isEmptyOrSpace((Object[])pObject)){
				return "";
			}else{
				return arrayToString((Object[])pObject);
			}
		}else if (pObject instanceof Collection<?>) {
			if(isEmptyOrSpace(((Collection<?>)pObject))){
				return "";
			}else{
				return arrayToString(((Collection<?>)pObject).toArray(new Object[0]));
			}
		}else if(pObject instanceof Clob){
			try {
				Clob tClob = (Clob)pObject;
				return tClob.getSubString(1,(int)tClob.length());
			} catch (Exception e) {
				throw new DBException(e);
			}
		}
		return String.valueOf(pObject);
	}
	
	/**
	 * 將物件轉成字串，並設定小數點位數
	 * @param pObject
	 * @return
	 */
	public static String getString(Object pObject, int decimal) {
		if(pObject == null){
			return "";
		}else if(Double.isNaN(((Number) pObject).doubleValue())){
			return "";	
		}else if(decimal <= 0){
			return String.valueOf(((Number) pObject).intValue());
		}else{
			String decimalStr = "0.";
			for(int i=0; i<decimal; i++)
				decimalStr += "0";
			DecimalFormat tFormat = new DecimalFormat(decimalStr);		
			return tFormat.format(pObject);
		}
	}
	
	private static String arrayToString(Object[] pObject){
		String tOut = Arrays.toString(pObject);
		if(tOut.length()<=2){
			return "";
		}else{
			return tOut;
		}
	}

	public static <T> List<T> arrayToList(T[] pObject){
		List<T> tOut = new ArrayList<T>();
		if(StringUtil.isNotEmptyOrSpace(pObject)){
			for (T t : pObject) {
				tOut.add(t);
			}
		}
		return tOut;
	}
	
	/**
	 * 傳入 1,2,3,4
	 * @param pStrId  1,2,3,4
	 * @return 回傳 list
	 */
	public static List<Integer> getIntegerList(String pStrId) {
		if(isEmptyOrSpace(pStrId)){
			return new ArrayList<Integer>(0);
		}
		return Arrays.asList(getInteger(pStrId.split(",")));
	}

	/**
	 * "1,2,3,,4" => [1,2,3,4]
	 * @param pStrId
	 * @param pSymbol
	 * @return
	 */
	public static List<String> getStringSplit(String pStrId,String pSymbol) {
		List<String> tOut = new ArrayList<String>();
		if(StringUtil.isNotEmptyOrSpace(pStrId)){
			for (String s : pStrId.split(pSymbol)) {
				if(isNotEmptyOrSpace(s)){
					tOut.add(s);
				}
			}
		}
		return tOut;
	}
	
	public static String arrayToString(Object[] pInherit, String pSymbol) {
		if(StringUtil.isNotEmptyOrSpace(pInherit)){
			StringBuffer tOut = new StringBuffer();
			for (Object o : pInherit) {
				tOut.append(o).append(pSymbol);
			}
			return trimLastChar(tOut.toString());
		}
		return EMPTY;
	}

	public static <T> List<T> getListContent(T ... pObject) {
		List<T> tOut = new ArrayList<T>();
		for (T t : pObject) {
			tOut.add(t);
		}
		return tOut;
	}

	public static String encodeMd5Hex(final String pText) { 
		return new String(DigestUtils.md5DigestAsHex(pText.getBytes()));
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T getObject(Class<T> pClass, String pValue) {
		T tOut = null;
		if(pClass.equals(String.class)){
			tOut = (T)((pValue != null)?pValue.trim():null);
		}else if(pClass.equals(int.class) || pClass.equals(Integer.class)){
			tOut = (T)new Integer(getInteger(pValue));
		}else if(pClass.equals(boolean.class) || pClass.equals(Boolean.class)){
			tOut = (T)new Boolean(getBoolean(pValue));
		}else{
			throw new RuntimeException("unknow type = " + pClass);
		}
		return tOut;
	}
	
	public static String readerToString(Reader pReader) {
		if(pReader == null) return null;
		StringBuilder tBuilder = new StringBuilder();
		try {
			BufferedReader tReader = new BufferedReader(pReader); 
			String tLine; 
			while((tLine=tReader.readLine())!=null) { 
				tBuilder.append(tLine); 
				tBuilder.append(CHANGE_LINE); 
			} 
		} catch (Exception e) {
			throw new DBException(e);
		}
		return tBuilder.toString();
	}
}